/**
 * 
 */
package idv.takeshi.software.productline.bookstore.application.service.dto;

import java.util.Collection;

import idv.takeshi.software.productline.bookstore.domain.model.useraccount.Role;
import idv.takeshi.software.productline.bookstore.domain.model.useraccount.UserAccount;
import idv.takeshi.software.productline.bookstore.domain.model.useraccount.UserAccountException;
import idv.takeshi.software.productline.bookstore.domain.model.useraccount.UserAccountFactory;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;

import org.apache.commons.lang.Validate;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

/**
 * A data-transfer Object for UserAccount model.
 * @author takeshi
 *
 */
public abstract class UserAccountDto <T extends UserAccount> {
	
	@Pattern(regexp = ".+")
	@NotNull
	private String accountName;
	
	@Pattern(regexp = ".*")
	private String password;
	
	@Pattern(regexp = ".*")
	private String confirmedPassword;
	
	@Pattern(regexp = ".*")
	private String newPassword;
	
	@Pattern(regexp = ".*")
	private String confirmedNewPassword;
	
	@Pattern(regexp = ".+")
	@NotNull
	private String zipCode;
	
	@Pattern(regexp = ".+")
	@NotNull
	private String contactAddress;
	
	@Pattern(regexp = "\\d*")
	private String contactPhoneNumber;
	
	@Pattern(regexp = "\\d+")
	@NotNull
	private String cellPhoneNumber;
	
	@Pattern(regexp = ".+@.+\\.[a-z]+")
	@NotNull
	private String emailAddress;
	
	
	/**
	 * Default constructor.
	 */
	public UserAccountDto(){}
	
	/**
	 * Initial this DTO by given userAccount model.
	 * @param userAccount
	 */
	public UserAccountDto(UserAccount userAccount){
		Validate.notNull(userAccount, "userAccount shall always not be null");
		
		this.accountName = userAccount.getAccountName();
//		this.password = userAccount.getPassword();
		this.zipCode = userAccount.getZipCode();
		this.contactAddress = userAccount.getContactAddress();
		this.contactPhoneNumber = userAccount.getContactPhoneNumber();
		this.cellPhoneNumber = userAccount.getCellPhoneNumber();
		this.emailAddress = userAccount.getEmailAddress();
	}
	
	/**
	 * @return the accountName
	 */
	public String getAccountName() {
		return accountName;
	}

	/**
	 * @param accountName the accountName to set
	 */
	public void setAccountName(String accountName) {
		this.accountName = accountName;
	}

	/**
	 * @return the password
	 */
	public String getPassword() {
		return password;
	}

	/**
	 * @param password the password to set
	 */
	public void setPassword(String password) {
		this.password = password;
	}

	/**
	 * @return the confirmedPassword
	 */
	public String getConfirmedPassword() {
		return confirmedPassword;
	}

	/**
	 * @param confirmedPassword the confirmedPassword to set
	 */
	public void setConfirmedPassword(String confirmedPassword) {
		this.confirmedPassword = confirmedPassword;
	}

	/**
	 * @return the newPassword
	 */
	public String getNewPassword() {
		return newPassword;
	}

	/**
	 * @param newPassword the newPassword to set
	 */
	public void setNewPassword(String newPassword) {
		this.newPassword = newPassword;
	}

	/**
	 * @return the confirmedNewPassword
	 */
	public String getConfirmedNewPassword() {
		return confirmedNewPassword;
	}

	/**
	 * @param confirmedNewPassword the confirmedNewPassword to set
	 */
	public void setConfirmedNewPassword(String confirmedNewPassword) {
		this.confirmedNewPassword = confirmedNewPassword;
	}

	/**
	 * @return the zipCode
	 */
	public String getZipCode() {
		return zipCode;
	}

	/**
	 * @param zipCode the zipCode to set
	 */
	public void setZipCode(String zipCode) {
		this.zipCode = zipCode;
	}

	/**
	 * @return the contactAddress
	 */
	public String getContactAddress() {
		return contactAddress;
	}

	/**
	 * @param contactAddress the contactAddress to set
	 */
	public void setContactAddress(String contactAddress) {
		this.contactAddress = contactAddress;
	}

	/**
	 * @return the contactPhoneNumber
	 */
	public String getContactPhoneNumber() {
		return contactPhoneNumber;
	}

	/**
	 * @param contactPhoneNumber the contactPhoneNumber to set
	 */
	public void setContactPhoneNumber(String contactPhoneNumber) {
		this.contactPhoneNumber = contactPhoneNumber;
	}

	/**
	 * @return the cellPhoneNumber
	 */
	public String getCellPhoneNumber() {
		return cellPhoneNumber;
	}

	/**
	 * @param cellPhoneNumber the cellPhoneNumber to set
	 */
	public void setCellPhoneNumber(String cellPhoneNumber) {
		this.cellPhoneNumber = cellPhoneNumber;
	}

	/**
	 * @return the emailAddress
	 */
	public String getEmailAddress() {
		return emailAddress;
	}
	
	/**
	 * Get Model instance.
	 * @param userAccountFactory
	 * @return
	 * @exception UserAccountException
	 */
	public abstract T createModel(UserAccountFactory userAccountFactory) throws UserAccountException;
	
	/**
	 * Load properties value of this DTO into given userAccount model.
	 * @param userAccount
	 * @return remove roles
	 * @exception UserAccountException
	 */
	public abstract Collection<Role> loadModel(UserAccount userAccount) throws UserAccountException;

	/**
	 * @param emailAddress the emailAddress to set
	 */
	public void setEmailAddress(String emailAddress) {
		this.emailAddress = emailAddress;
	}


	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@SuppressWarnings("unchecked")
	@Override
	public boolean equals(Object obj) {
		if (obj == null) { return false; }
		   if (obj == this) { return true; }
		   if (obj.getClass() != getClass()) {
		     return false;
		   }
		   UserAccountDto rhs = (UserAccountDto) obj;
		   return new EqualsBuilder()
			   .append(this.accountName, rhs.accountName)
			   .append(this.password, rhs.password)
			   .append(this.confirmedPassword, rhs.confirmedPassword)
			   .append(this.newPassword, rhs.newPassword)
			   .append(this.confirmedNewPassword, rhs.confirmedNewPassword)
			   .append(this.zipCode, rhs.zipCode)
			   .append(this.contactAddress, rhs.contactAddress)
			   .append(this.contactPhoneNumber, rhs.contactPhoneNumber)
			   .append(this.cellPhoneNumber, rhs.cellPhoneNumber)
			   .append(this.emailAddress, rhs.emailAddress)
		       .isEquals();
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		return new HashCodeBuilder(89, 97).
	       append(this.accountName).
	       append(this.password).
	       append(this.confirmedPassword).
	       append(this.newPassword).
	       append(this.confirmedNewPassword).
	       append(this.zipCode).
	       append(this.contactAddress).
	       append(this.contactPhoneNumber).
	       append(this.cellPhoneNumber).
	       append(this.emailAddress).
	       toHashCode();
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE);
	}
	

}
